package com.jiangli.controller.admin;


import com.jiangli.result.Result;
import com.jiangli.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
// Java标准库
import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.UUID;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.ImageWriteParam;
import javax.imageio.IIOImage;
import javax.imageio.stream.ImageOutputStream;


@RestController
@RequestMapping("/admin/common")
@Api(tags=" 管理端通用接口")
@Slf4j
public class CommonController {
    private static final String LOCAL_SAVE_PATH = "D:/截图文件/";

    @Autowired
    AliOssUtil aliOssUtil;

    // 设置目标压缩大小为100KB
    private static final long TARGET_SIZE = 25 * 1024;
    // 可接受的误差范围：±10KB
    private static final long ACCEPTABLE_RANGE = 10 * 1024;

    @PostMapping("/upload")
    @ApiOperation("上传文件，超过100KB自动压缩，最大支持10MB原始文件")
    public Result<String> upload(@RequestParam("file") MultipartFile file) throws IOException {
        // 校验文件是否为空
        if (file.isEmpty()) {
            return Result.error("上传文件不能为空");
        }

        log.info("文件上传:{}，原始大小:{}KB",
                file.getOriginalFilename(),
                file.getSize() / 1024);

        // 业务层校验文件大小（与配置文件保持一致）
        if (file.getSize() > 10 * 1024 * 1024) {
            log.warn("文件过大，超过10MB限制:{}", file.getOriginalFilename());
            return Result.error("文件大小不能超过10MB");
        }

        byte[] fileBytes;
        // 仅对图片文件进行压缩，且原始大小超过100KB时才触发压缩
        if (file.getSize() > TARGET_SIZE && isImageFile(file)) {
            // 压缩到接近100KB
            fileBytes = compressImageToTargetSize(file, TARGET_SIZE);
            log.info("文件压缩完成，压缩后大小:{}KB", fileBytes.length / 1024);
        } else {
            // 非图片或小于100KB，直接使用原文件
            fileBytes = file.getBytes();
        }


        // 生成文件名并上传
        String originalFilename = file.getOriginalFilename();
        String extension = getFileExtension(originalFilename);
        String objectName = UUID.randomUUID() + extension;
        String filePath = aliOssUtil.upload(fileBytes, objectName);

        return Result.success(filePath);
    }

    /**
     * 判断是否为图片文件（根据MIME类型）
     */
    private boolean isImageFile(MultipartFile file) {
        String contentType = file.getContentType();
        return contentType != null && contentType.startsWith("image/");
    }

    /**
     * 获取文件扩展名（如.jpg、.png）
     */
    private String getFileExtension(String originalFilename) {
        if (originalFilename != null && originalFilename.contains(".")) {
            return originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        return ".jpg"; // 默认扩展名
    }

    /**
     * 核心方法：将图片压缩到目标大小（接近100KB）
     */
    private byte[] compressImageToTargetSize(MultipartFile file, long targetSize) throws IOException {
        BufferedImage originalImage = ImageIO.read(file.getInputStream());
        String format = getFileExtension(file.getOriginalFilename()).replace(".", "");
        if (format.isEmpty()) {
            format = "jpg";
        }

        // 特殊处理PNG格式（转为JPG以获得更好的压缩率）
        if ("png".equalsIgnoreCase(format)) {
            format = "jpg";
            originalImage = convertPngToJpg(originalImage);
        }

        BufferedImage currentImage = originalImage;
        byte[] compressedData;

        // 初始缩放比例（根据原始图片大小动态调整）
        float scale = calculateInitialScale(originalImage, file.getSize());
        currentImage = resizeImage(currentImage, scale);

        // 二分法寻找最佳质量参数，确保更接近目标大小
        compressedData = findOptimalQuality(currentImage, format, targetSize);

        // 如果经过质量调整仍超过目标，进一步缩小尺寸并再次调整质量
        int resizeAttempts = 0;
        while (compressedData.length > targetSize + ACCEPTABLE_RANGE && resizeAttempts < 5) {
            resizeAttempts++;
            currentImage = resizeImage(currentImage, 0.8f); // 每次缩小20%
            compressedData = findOptimalQuality(currentImage, format, targetSize);
        }
//        // 保存压缩后的文件到本地
//        saveCompressedFileToLocal(compressedData, file.getOriginalFilename(), format);
        return compressedData;
    }

    /**
     * 根据原始图片大小计算初始缩放比例
     */
    private float calculateInitialScale(BufferedImage image, long originalSize) {
        if (originalSize > 5 * 1024 * 1024) { // 5MB以上
            return 0.3f; // 缩小到30%
        } else if (originalSize > 2 * 1024 * 1024) { // 2-5MB
            return 0.5f; // 缩小到50%
        } else if (originalSize > 1 * 1024 * 1024) { // 1-2MB
            return 0.6f; // 缩小到60%
        } else { // 1MB以下
            return 0.8f; // 缩小到80%
        }
    }

    /**
     * 使用二分法寻找最佳质量参数
     */
    private byte[] findOptimalQuality(BufferedImage image, String format, long targetSize) throws IOException {
        float low = 0.1f;
        float high = 1.0f;
        float mid = 0.5f;
        byte[] bestData = null;
        long bestSize = Long.MAX_VALUE;

        // 最多尝试10次二分查找
        for (int i = 0; i < 10; i++) {
            byte[] currentData = compressWithQuality(image, format, mid);
            long currentSize = currentData.length;

            // 记录最接近目标的值
            if (Math.abs(currentSize - targetSize) < Math.abs(bestSize - targetSize)) {
                bestSize = currentSize;
                bestData = currentData;
            }

            // 如果在可接受范围内，提前退出
            if (currentSize >= targetSize - ACCEPTABLE_RANGE && currentSize <= targetSize + ACCEPTABLE_RANGE) {
                return currentData;
            }

            // 调整二分范围
            if (currentSize > targetSize) {
                high = mid;
            } else {
                low = mid;
            }
            mid = (low + high) / 2;
        }

        return bestData != null ? bestData : compressWithQuality(image, format, 0.5f);
    }

    /**
     * 将PNG图片转为JPG，处理透明背景
     */
    private BufferedImage convertPngToJpg(BufferedImage pngImage) {
        BufferedImage jpgImage = new BufferedImage(
                pngImage.getWidth(),
                pngImage.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );

        // 填充白色背景
        Graphics2D g = jpgImage.createGraphics(); // 这里不会再报错
        try {
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, jpgImage.getWidth(), jpgImage.getHeight());
            g.drawImage(pngImage, 0, 0, null);
        } finally {
            // 手动释放图形上下文资源，这是必须的
            g.dispose();
        }

        return jpgImage;
    }

    /**
     * 按比例缩小图片尺寸
     * @param image 原始图片
     * @param scale 缩放比例（如0.7表示缩小到70%）
     */
    private BufferedImage resizeImage(BufferedImage image, float scale) {
        int originalWidth = image.getWidth();
        int originalHeight = image.getHeight();
        // 计算新尺寸（确保至少有100x100像素，避免过小）
        int newWidth = Math.max((int) (originalWidth * scale), 100);
        int newHeight = Math.max((int) (originalHeight * scale), 100);

        BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = resizedImage.createGraphics();
        try {
            // 保持图片平滑
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(image, 0, 0, newWidth, newHeight, null);
        } finally {
            // 手动关闭图形上下文
            g.dispose();
        }
        return resizedImage;
    }

    /**
     * 按指定质量压缩图片
     */
    private byte[] compressWithQuality(BufferedImage image, String format, float quality) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
        if (!writers.hasNext()) {
            throw new IOException("未找到支持的图片格式: " + format);
        }

        ImageWriter writer = writers.next();
        ImageWriteParam param = writer.getDefaultWriteParam();

        // 设置压缩模式和质量
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(quality);

        // 写入压缩后的图片到字节流
        try (ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream)) {
            writer.setOutput(ios);
            writer.write(null, new IIOImage(image, null, null), param);
        } finally {
            writer.dispose(); // 确保资源释放
        }

        return outputStream.toByteArray();
    }
    /**
     * 将压缩后的文件保存到本地目录
     */
//    private void saveCompressedFileToLocal(byte[] data, String originalFilename, String format) throws IOException {
//        // 创建保存目录（如果不存在则自动创建）
//        File saveDir = new File(LOCAL_SAVE_PATH);
//        if (!saveDir.exists()) {
//            saveDir.mkdirs(); // 递归创建目录
//        }
//
//        // 生成保存的文件名（原始文件名_压缩后.格式）
//        String baseName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
//        String saveFileName = baseName + "_compressed." + format;
//        File saveFile = new File(saveDir, saveFileName);
//
//        // 写入文件到本地
//        try (FileOutputStream fos = new FileOutputStream(saveFile)) {
//            fos.write(data);
//        }
//
//        log.info("压缩后的文件已保存到本地: {}", saveFile.getAbsolutePath());
//    }
}
